<template>
  <div ref="containerRef">
    <slot></slot>
    <!-- 保证相对于视口fixed -->
    <teleport to="body">
      <transition name="el-zoom-in-top">
        <div
          v-if="visible"
          v-size-observe="handleSizeChange"
          class="context-menu--box"
          :style="{ left: pos.posX + 'px', top: pos.posY + 'px' }"
        >
          <div
            v-for="(item, index) in menus"
            :key="index"
            :class="['context-menu--item', 'flex', { 'is-disabled': item.disabled }]"
            @click="handleSelect(item, index)"
          >
            <icon
              v-if="item.icon"
              :name="item.icon"
              size="16"
              class="context-menu--item-icon"
            />
            <div>{{ item.label }}</div>
          </div>
        </div>
      </transition>
    </teleport>
  </div>
</template>

<script setup>
import useContextMenu from './useContextMenu'
import useViewport from './useViewport'

defineProps({
  menus: {
    type: Array,
    default: () => [],
  },
})
const emit = defineEmits(['select'])

const containerRef = ref(null)
const width = ref(0)
const height = ref(0)

const { visible, x, y } = useContextMenu(containerRef)
const { vw, vh } = useViewport()

const pos = computed(() => {
  let posX = x.value
  let posY = y.value
  const w = width.value
  const h = height.value
  // 大于极限位置重新计算：鼠标位置 - 菜单宽度，纵向也是如此
  if (posX > vw.value - w) {
    posX -= w
  }
  if (posY > vh.value - h) {
    posX = vh.value - h
  }

  return {
    posX,
    posY,
  }
})

function handleSelect(item, index) {
  if (item.disabled) return
  emit('select', { ...item, index })
  visible.value = false
}

function handleSizeChange(size) {
  width.value = size.width
  height.value = size.height
}
</script>

<style scoped lang="scss">
html.dark {
  .is-disabled {
    color: #525457;
  }

  .context-menu--item {
    &.is-disabled:hover {
      color: #525457;
      background-color: transparent;
    }
  }
}

.context-menu {
  &--box {
    position: fixed;
    background-color: var(--el-bg-color);
    border: 1px solid var(--el-border-color);
    border-radius: 4px;
  }

  &--item {
    padding: $space-small-s $space-small;
    border-bottom: 1px solid var(--el-border-color);
    font-size: $font-size-medium;
    cursor: pointer;

    &:hover {
      color: var(--el-color-primary);
      background-color: var(--el-color-primary-light-9);
    }

    &.is-disabled:hover {
      color: #a8abb2;
      background-color: transparent;
    }

    &:first-child {
      border-top-left-radius: 4px;
      border-top-right-radius: 4px;
    }

    &:last-child {
      border-bottom: none;
      border-bottom-left-radius: 4px;
      border-bottom-right-radius: 4px;
    }

    &-icon {
      margin-right: 4px;
    }
  }
}

.is-disabled {
  cursor: not-allowed;
  color: #a8abb2;
}
</style>
